package com.wlz.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 *   防御CSRF攻击策略
 *      1）验证 HTTP Referer 字段
 *      2) 在请求地址中添加 token 并验证
 *      3) 在 HTTP 头中自定义属性并验证
 *
 *      从 Spring Security4开始CSRF防护默认开启，默认会拦截请求，进行CSRF处理。CSRF为了保证不是其
 *   他第三方网站访问，要求访问时携带参数名为 _csrf 值为token(token 在服务端产生，在渲染请求页面时
 *   埋入页面)的内容，如果token和服务端的token匹配成功，则正常访问。
 *
 * @author wlz
 */
@Configuration
public class WebSecurityCsrfConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService myUserDetailsService3;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //设置UserDetailsService的实现类
        auth.userDetailsService(myUserDetailsService3);

    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin() //表单提交
           //.usernameParameter("username1212")  //自定义username入参,必须和表单name值一致
           //.passwordParameter("password1212")
            .loginPage("/showLogin") //自定义登录页面
            .loginProcessingUrl("/user/login")  //登录访问路径，必须和表单提交接口一样
            .successForwardUrl("/main")   //认证成功之后转发的路径,必须是Post请求
            .failureForwardUrl("/toerror")  //认证失败之后转发的路径,必须是Post请求
            //授权
            .and().authorizeRequests()
            //设置哪些路径可以直接访问，不需要认证
            .antMatchers("/user/login","/showLogin","/toerror").permitAll()
            .anyRequest().authenticated()  //需要认证
            .and().csrf().disable(); //关闭csrf防护
    }

}
